package com.lethe.medical.base;

import com.lethe.medical.base.annotation.MethodAnnotation;
import org.apache.commons.beanutils.BeanUtils;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.Map;

public class BaseServlet extends HttpServlet {
    private String ctxPath = "";

    private static final long serialVersionUID = 1L;
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        System.out.println("BaseServlet执行");
        String method = getMethod(request);
        System.out.println("method = "+method);

        page(request,response);

        invoke(request,response);
    }

    //分页参数接收

    /**
     * 获取对应的方法的路径or名称
     * @param request
     * @return
     * @throws ServletException
     * @throws IOException
     */
    public String getMethod(HttpServletRequest request)throws IOException {
        String uri = request.getRequestURI();
        ctxPath = request.getContextPath();
        String url = uri.substring(ctxPath.length() + 1);
        String[] lists = url.split("/");

        String method = "";

        if(lists.length > 0){
            method = lists[lists.length-1];
            //System.out.println(lists[1]);
        }
        return method;
    }

    /**
     * 执行指定的方法
     * @param request
     * @param response
     * @throws IOException
     */
    protected void invoke(HttpServletRequest request, HttpServletResponse response) throws IOException{
        Class<?> clz =  this.getClass();
        int count=0;
        boolean flag = true;
        String method = getMethod(request);

        //加载目标类的所有方法
        Method[] methods = clz.getDeclaredMethods();
        //遍历所有方法
        for(Method m : methods){

            //判断目标方法是否有MethodAnnotation的注解
            if(m.isAnnotationPresent(MethodAnnotation.class)){
                MethodAnnotation methodAnnotation = m.getAnnotation(MethodAnnotation.class);

                //判断方法名是否和url的方法名一致
                if(methodAnnotation.method().equals(method)){
                    try {
                        //所有匹配完成，执行目标方法
                        m.invoke(this, request,response);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    flag = true;
                    break;
                }else{
                    flag = false;
                }
            }else{
                count++;
            }
        }
        if(!flag){
            response.getWriter().write("'没有找到相应的操作，请查看method中的参数是否配置出错！')");
            return;
        }
        if(count==methods.length){
            response.getWriter().write("'没有添加任何方法映射！'");
            return;
        }

    }

    /**
     * 如果路径中包括page，则拼接路径，转发到该页面
     * @param request
     * @param response
     * @throws IOException
     */
    public void page(HttpServletRequest request, HttpServletResponse response) throws IOException{
        //如果uri中有page，则拼接路径，转发到这个路径
        String uri = request.getRequestURI();

        if(uri.contains("page")){
            System.out.println(uri);
        }
    }


    /**
     * 利用getParameterNames方法，把参数转为bean
     * @param request
     * @param beanClass
     * @param <T>
     * @return
     */
    public <T> T requestToBean(HttpServletRequest request, Class<T> beanClass) {
        T t = null;
        try {
            t = beanClass.newInstance();
            // 使用getParameterNames()获取 参数名（枚举类型）
            Enumeration<String> parameterNames = request.getParameterNames();
            // 测试此枚举是否包含更多的元素
            while (parameterNames.hasMoreElements()) {
                // 如果此枚举对象至少还有一个可提供的元素，则返回此枚举的下一个元素。
                String name = parameterNames.nextElement();
                // 获取参数name对应的value
                String value = request.getParameter(name);
                // 对bean属性进行赋值
                BeanUtils.setProperty(t, name, value);
            }

        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return t;
    }

    /**
     * 利用getParameterMap方法，转为bean
     * @param request
     * @param t
     * @param <T>
     * @return
     */
    public <T> T param2Bean(HttpServletRequest request, T t) {
        // 获得参数map
        Map<String, String[]> parameterMap = request.getParameterMap();
        System.out.println(parameterMap);
        try {
            // 将一个Map集合中的数据封装到指定对象bean中
            BeanUtils.populate(t, parameterMap);
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return t;
    }


    /**
     * 请求转发
     * @param request
     * @param response
     * @param jspName
     * @throws ServletException
     * @throws IOException
     */
    public void dispatcher(HttpServletRequest request,HttpServletResponse response, String jspName) throws ServletException, IOException{
        String jsp = "jsp";
        //传过来的参数中有jsp字样
        if(jspName.indexOf(jsp)>0){
            //如果页面在根目录，如 index.jsp，则不用拼接路径
            request.getRequestDispatcher("/"+jspName).forward(request, response);
        }else{
            //如果页面在web-inf目录里面，那么jspname只要写jsp名字而不用加后缀，要拼接路径
            request.getRequestDispatcher("/WEB-INF/page/"+jspName + ".jsp").forward(request, response);
        }
    }

    /**
     * 重定向
     * @param request
     * @param response
     * @param jspName
     * @throws ServletException
     * @throws IOException
     */
    public void sendRedirect(HttpServletRequest request, HttpServletResponse response, String jspName) throws IOException{

        String jsp = "jsp";
        //传过来的参数中有jsp字样
        if(jspName.indexOf(jsp)>0){
            //如果页面在根目录，如 index.jsp，则不用拼接路径
            //重定向时的路径一定要带项目名称
            response.sendRedirect(request.getContextPath()+"/"+jspName);
        }else{
            //如果页面在web-inf目录里面，那么jspname只要写jsp名字而不用加后缀，要拼接路径
            //重定向时的路径一定要带项目名称
            response.sendRedirect(request.getContextPath()+"/WEB-INF/page/"+jspName+".jsp");
        }


    }
}
